package com.young.ysepay.service.impl;

import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.shade.com.alibaba.fastjson.JSON;
import com.aliyun.openservices.shade.com.alibaba.fastjson.serializer.SerializerFeature;
import com.young.ysepay.domain.YsWechatpayReceiptDO;
import com.young.ysepay.dto.YsPayDTO;
import com.young.ysepay.mq.YsReturnMQConfig;
import com.young.ysepay.service.*;
import com.young.ysepay.utils.*;

import com.young.ysepay.utils.apiresult.ApiResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;



/**
 * 银盛微信支付
 * @Author Vincentxin
 * @Date 2019-05-29
 */
@Service
public class YsWeChatPayServiceImpl implements YsWeChatPayService {

    private static Logger log = LoggerFactory.getLogger(YsWeChatPayServiceImpl.class);
    @Autowired
    private YsBusinessPramService ysBusinessPramService;

    @Autowired
    private YsBuildRequestParaService ysBuildRequestParaService;

    @Autowired
    private YsVerifyJsonSignService ysVerifyJsonSignService;

    @Autowired
    private Producer producer;

    @Autowired
    YsWechatpayReceiptService ysWechatpayReceiptService ;

    @Value("${MiniAppPayNotifyUrl}")
    private String miniAppPayNotifyUrl;
    /**
     * 微信小程序支付
     * @param paramMap
     * @return
     */
    @Override
    public Map<String, Object> miniAppPerPay(Map<String, String> paramMap) {

        String temp;
        //交易描述
        temp = paramMap.get("subject");
        String subject = temp;
        //交易金额
        temp = paramMap.get("total_amount");
        String totalAmount = temp ;
        //补贴金额
        temp = paramMap.get("mer_amount");
        String merAmount = temp ;
        //微信用户openId
        temp = paramMap.get("sub_openid");
        String subOpenid = temp ;
        //平台订单号
        temp = paramMap.get("out_trade_no");
        String outTradeNo = temp ;

        if (StringUtils.isBlank(subject) || StringUtils.isBlank(totalAmount)
                || StringUtils.isBlank(outTradeNo) || StringUtils.isBlank(subOpenid)) {
            return ReturnUtils.paramIsNull();
        }
        Map<String, Object> realResponse = new HashMap<String, Object>();
        YsPayDTO ysPayDTO=this.ysBusinessPramService.ysBusinessPram();
        Map<String, String> param = new HashMap<String, String>();
        param.put("method", "ysepay.online.weixin.pay");
        param.put("partner_id", ysPayDTO.getPARTNER_ID());
        param.put("timestamp", DateFormatHelper.getNowTimeStr());
        param.put("charset", ysPayDTO.getDEFAULT_CHARSET());
        param.put("sign_type", ysPayDTO.getSIGN_ALGORITHM());
        param.put("notify_url", miniAppPayNotifyUrl);
        param.put("version", ysPayDTO.getVERSION());


        Map<String, String> biz_contentMap = new HashMap<String, String>();
        biz_contentMap.put("out_trade_no", outTradeNo);
        biz_contentMap.put("shopdate", DateUtil.getDateFormat(new Date(),DateUtil.dtShort));
        biz_contentMap.put("subject", subject);
        biz_contentMap.put("total_amount", totalAmount);
        biz_contentMap.put("seller_id", ysPayDTO.getPARTNER_ID());
        biz_contentMap.put("seller_name", ysPayDTO.getSELLER_NAME());
        biz_contentMap.put("timeout_express", ysPayDTO.getTIMEOUT_EXPRESS());
        biz_contentMap.put("business_code", ysPayDTO.getBUSINESS_CODE());
        biz_contentMap.put("sub_openid", subOpenid);
        if (StringUtils.isNotBlank(merAmount)){
            biz_contentMap.put("mer_amount", merAmount);
        }

        //TODO 使用枚举 （代表小程序支付）1 小程序 2或者不填代表 公众号
        biz_contentMap.put("is_minipg", "1");
        //小程序appId  或这公众共appId 看支付业务情况
        biz_contentMap.put("appid", ysPayDTO.getAPP_ID());
//        String payChannelFee = new BigDecimal(totalAmount).multiply(new BigDecimal("0.0045")).setScale(2, RoundingMode.HALF_UP).toEngineeringString();
//        biz_contentMap.put("mer_amount",payChannelFee);
        param.put("biz_content", JSON.toJSONString(biz_contentMap));
        log.info("miniAppPerPay--------------请求银盛微信支付参数"+param);
        try {
            //签名
            Map<String, String> sPara = ysBuildRequestParaService.buildRequestPara(param);
            //发起请求
            log.info("签名完成的参数：{}",sPara);
             String returnString = Https.httpsSend(ysPayDTO.getYSEPAY_GATEWAY_URL(), sPara);
            //回执参数JSON转map
            Map<String,Object> resultMap = (Map<String,Object>) JSON.parse(returnString);

            Map<String,String> obj = (Map<String, String>) resultMap.get("ysepay_online_weixin_pay_response");
            String sign = resultMap.get("sign").toString();

            realResponse.putAll(obj) ;
            realResponse.put("sign", sign);
            int begin = returnString.indexOf("ysepay_online_weixin_pay_response");
            String content = returnString.substring(begin);
            content = content.replace("ysepay_online_weixin_pay_response","");
            content = content.substring(2,content.length()-1);
            log.info("miniAppPerPay--------------调用银盛微信支付同步回执response"+content);
            //银盛同步回执信息保存
         /*   if(null != content || !content.equals("")){
                Map<String, Object> syncMap = JSONUtils.jsonToMap(content);
                saveSyncWechatPay(syncMap);
            }*/
            //TODO 验证签名总是出错，需要确认一下验证签名的responseBody到底是哪些参数。
            boolean verifyResult =ysVerifyJsonSignService.verifyJsonSign(sign, content, "utf-8");
            realResponse.put("verifyResult", verifyResult);
            return realResponse;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e1) {
            e1.printStackTrace();
        }catch (Exception e2){
            e2.printStackTrace();
        }finally{
            return realResponse;
        }
    }

    private void saveSyncWechatPay(Map<String, Object> syncMap) {
        log.error("saveSyncWechatPay-------保存同步回执信息参数"+JSONUtils.objectToJson(syncMap));
            //同步回执
            String code = syncMap.get("code").toString();
            //code:10000只代表接口调用成功并非同步请求成功
            String outTradeNoSync = syncMap.get("out_trade_no").toString();
            String tradeStatusSync = syncMap.get("trade_status").toString();
            YsWechatpayReceiptDO ysWechatpayReceiptDO = new YsWechatpayReceiptDO();
            try {
                if(code.equals("10000")){
                    //获取回执参数
                    String totalAmountSync = syncMap.get("total_amount").toString();
                    String tradeNoSync = syncMap.get("trade_no").toString();
                    //保存数据
                    ysWechatpayReceiptDO.setGmtCreate(new Date());
                    ysWechatpayReceiptDO.setGmtModified(new Date());
                    ysWechatpayReceiptDO.setIsDelete("1");
                    ysWechatpayReceiptDO.setOutTradeNo(outTradeNoSync);
                    ysWechatpayReceiptDO.setResponseType("1");
                    ysWechatpayReceiptDO.setTotalAmount(new BigDecimal(totalAmountSync));
                    ysWechatpayReceiptDO.setTradeStatus(tradeStatusSync);
                    ysWechatpayReceiptDO.setTradeNo(tradeNoSync);
                    ysWechatpayReceiptService.save(ysWechatpayReceiptDO);
                }else {
                    //接口调用失败
                    ysWechatpayReceiptDO.setOutTradeNo(outTradeNoSync);
                    ysWechatpayReceiptDO.setTradeStatus(tradeStatusSync);
                    ysWechatpayReceiptDO.setResponseType("1");
                    ysWechatpayReceiptDO.setIsDelete("1");
                    ysWechatpayReceiptDO.setGmtCreate(new Date());
                    ysWechatpayReceiptDO.setGmtModified(new Date());
                    ysWechatpayReceiptService.save(ysWechatpayReceiptDO);
                }
            } catch (Exception e) {
                log.error("銀盛同步回执信息保存失败"+e.getMessage());
                e.printStackTrace();
            }
    }

    /**
     * 银盛微信异步通知回执处理
     * @param params 异步回执参数
     * @param response
     */
    @Override
    public void weChatPayCallBack(Map<String,String> params ,HttpServletResponse response) {
        //TODO 验证签名
        PrintWriter out = null;
        log.info("银盛微信支付异步回执参数"+JSONUtils.objectToJson(params));
        try {
            //saveAsyncWechatPay(params);
            out = response.getWriter();
            boolean res = ysVerifyJsonSignService.verifySign(params);
            log.info("签名验证情况:"+res);
            if (res){
                String msg = JSON.toJSONString(params, SerializerFeature.DisableCircularReferenceDetect);
                Message message = new Message(YsReturnMQConfig.PAYTOPIC,YsReturnMQConfig.PAY_TAG,msg.getBytes());
                producer.send(message);
                log.info("返回结果：SUCCESS");
                out.println("success");
            }else{
                log.info("返回结果：FAIL");
                out.println("fail");
            }
        }catch (Exception e){
            log.error("");
            e.printStackTrace();
        }finally {
            if (out != null){
                out.close();
            }
        }


    }

    private void saveAsyncWechatPay(Map<String,String> params) {
        YsWechatpayReceiptDO ysWechatpayReceiptDO = new YsWechatpayReceiptDO();
        log.error("saveAsyncWechatPay-----------保存异步回执信息参数"+JSONUtils.objectToJson(params));
        System.out.println("请求的参数"+params.toString());
        try {
            String out_trade_no = params.get("out_trade_no");
            String sign = params.get("sign");
            String sign_type = params.get("sign_type");
            String notify_type = params.get("notify_type");
            String notify_time = params.get("notify_time");
            String total_amount = params.get("total_amount");
            String trade_no = params.get("trade_no");
            String trade_status = params.get("trade_status");
            String account_date = params.get("account_date");
            ysWechatpayReceiptDO.setGmtCreate(new Date());
            ysWechatpayReceiptDO.setGmtModified(new Date());
            ysWechatpayReceiptDO.setIsDelete("1");
            ysWechatpayReceiptDO.setResponseType("2");
            ysWechatpayReceiptDO.setTradeStatus(trade_status);
            ysWechatpayReceiptDO.setOutTradeNo(out_trade_no);
            ysWechatpayReceiptDO.setTradeNo(trade_no);
            ysWechatpayReceiptDO.setTotalAmount(new BigDecimal(total_amount));
            ysWechatpayReceiptDO.setSignType(sign_type);
            ysWechatpayReceiptDO.setNotifyType(notify_type);
            ysWechatpayReceiptDO.setNotifyTime(notify_time);
            ysWechatpayReceiptDO.setSign(sign);
            ysWechatpayReceiptDO.setAccountDate(account_date);
            ysWechatpayReceiptService.save(ysWechatpayReceiptDO);
            log.error("銀盛异步回执信息保存"+ysWechatpayReceiptDO);
        } catch (Exception e) {
            log.error("銀盛异步回执信息保存失败"+e.getMessage());
            e.printStackTrace();
        }

    }

}
